Neural Network demo (not tested yet)

Start a Mosquitto container first. For example:

  • Use codes\_demo\1_start_broker.sh to start a Mosquitto container on Raspberry Pi.
  • Config files are in mqtt_config\mqtt.
  • set allow_anonymous true in mqtt_config\mqtt\config\mosquitto.conf to allow anonymous client.

Getting Started

What this notebook does:

  • Using:
    • a client on PC
    • 6 ESP8266 modules (NodeMCU and D1 mini) as remote nodes
  • List connected nodes
  • Rename remote nodes
  • Setup neural network configuration (connections, weights, thresholds)
  • Fire up neurons and get logs.

In [2]:
import os
import sys
import time
 
sys.path.append(os.path.abspath(os.path.join(os.path.pardir, '..\\codes', 'client')))
sys.path.append(os.path.abspath(os.path.join(os.path.pardir, '..\\codes', 'node')))
sys.path.append(os.path.abspath(os.path.join(os.path.pardir, '..\\codes', 'shared')))
sys.path.append(os.path.abspath(os.path.join(os.path.pardir, '..\\codes', 'micropython')))
 
import client
from collections import OrderedDict

In [4]:
import pandas as pd
from pandas import DataFrame
from time import sleep
REFRACTORY_PERIOD = 0.1   # 0.1 seconds

In [5]:
# Each ESP8266 modules represents a neuron. We have 6 of them.
neurons = ['neuron_x1', 'neuron_x2', 'neuron_h1', 'neuron_h2', 'neuron_h3', 'neuron_y']

Start client


In [6]:
the_client = client.Client()
the_client.start()

while not the_client.status['Is connected']:            
    time.sleep(1)
    print('Node not ready yet.')


My name is Client_366

Sending 277 bytes
Message:
OrderedDict([('command', 'set connection name'), ('correlation_id', '2017-02-09 01:51:58.999000'), ('kwargs', {'name': 'Client_366'}), ('message_id', '2017-02-09 01:51:58.999000'), ('message_type', 'command'), ('need_result', True), ('receiver', 'Hub'), ('reply_to', 'Client_366'), ('sender', 'Client_366')])


[Connected: ('192.168.0.114', 1883)]
[Listen to messages]
Node not ready yet.

Utility functions


In [7]:
# Ask Hub for a list of connected nodes
def list_nodes():
    the_client.node.worker.roll_call()
    time.sleep(2)
    remote_nodes = sorted(the_client.node.worker.contacts.keys())

    print('\n[____________ Connected nodes ____________]\n')
    print('\nConnected nodes:\n{}\n'.format(remote_nodes))
        
    return remote_nodes

In [8]:
def reset_node(node):
    message = {'message_type': 'exec',
               'to_exec': 'import machine;machine.reset()'}
    the_client.request(node, message)

In [9]:
def rename_node(node, new_name):
    
    with open('temp.py', 'w') as f:
        f.write('WORKER_NAME = ' + '\"' + new_name + '\"\n')
        
    with open('temp.py') as f:
        script = f.read()
        message = {'message_type': 'file',
                   'file': script,
                   'kwargs': {'filename': 'worker_config.py'}}
        the_client.request(node, message)
    
    os.remove('temp.py')
    
    time.sleep(1)
    reset_node(node)
    

def rename_nodes(nodes, neurons):    
    i = 0 
    for node in nodes:
        if node != the_client.node.worker.name:  # exclude client self
            rename_node(node, neurons[i])
            i += 1

In [10]:
def fire(node):
    message = {'message_type': 'function',
               'function': 'fire'}
    the_client.request(node, message) 

def addConnection(node, neuron):
    message = {'message_type': 'function',
               'function': 'addConnection',
               'kwargs': {'neuron_id': neuron}}
    the_client.request(node, message) 
    
def set_connections(node, connections):
    message = {'message_type': 'function',
               'function': 'setConnections',
               'kwargs': {'connections': connections}}
    the_client.request(node, message)     
    
def get_connections(node):
    message = {'message_type': 'function',
               'function': 'getConnections', 
               'need_result': True}
    _, result = the_client.request(node, message) 
    return result.get()    

def setWeight(node, neuron, weight):
    message = {'message_type': 'function',
               'function': 'setWeight',
               'kwargs': {'neuron_id': neuron,
                          'weight': weight,}}
    the_client.request(node, message) 

def setThreshold(node, threshold):
    message = {'message_type': 'function',
               'function': 'setThreshold',
               'kwargs': {'threshold': threshold}}
    the_client.request(node, message) 
        
def getConfig(node):
    message = {'message_type': 'function',
               'function': 'getConfig', 
               'need_result': True}
    _, result = the_client.request(node, message) 
    return result.get()

def getLog(node):
    message = {'message_type': 'function',
               'function': 'getLog', 
               'need_result': True}
    _, result = the_client.request(node, message) 
    return result.get()

def emptyLog(node):
    message = {'message_type': 'function',
               'function': 'emptyLog'}
    the_client.request(node, message)
    
def emptyLogs():
    for neuron in neurons:
        emptyLog(neuron) 
        
def mergeLogs():
    logs = []
    
    for neuron in neurons:
        if neuron != the_client.node.worker.name:  # exclude client self
            currentLog = getLog(neuron)
            if currentLog:
                logs += currentLog 
            
    df = DataFrame(list(logs), columns = ['time', 'neuron', 'message']) 
    df.set_index('time', inplace = True)
    df.sort_index(inplace = True)
    
    return df

In [11]:
def printConfig(neuron):
    print('{0:_^78}\n {1}\n'.format(neuron + " config:", getConfig(neuron)))

In [94]:
# fire('NodeMCU_1dsc000')

List connected nodes


In [ ]:
remote_nodes = list_nodes()

Rename nodes


In [ ]:
rename_nodes(remote_nodes, neurons) 
time.sleep(2)
remote_nodes = list_nodes()

In [ ]:
remote_nodes = list_nodes()

Setup network configuration

Clear log files


In [ ]:
emptyLogs()

Setup connections


In [ ]:
addConnection('neuron_x1', 'neuron_h1')
addConnection('neuron_x1', 'neuron_h2')

addConnection('neuron_x2', 'neuron_h2')
addConnection('neuron_x2', 'neuron_h3')

addConnection('neuron_h1', 'neuron_y')
addConnection('neuron_h2', 'neuron_y')
addConnection('neuron_h3', 'neuron_y')

Setup weights


In [ ]:
setWeight('neuron_h1', 'neuron_x1', 1) 
setWeight('neuron_h2', 'neuron_x1', 1) 

setWeight('neuron_h2', 'neuron_x2', 1) 
setWeight('neuron_h3', 'neuron_x2', 1) 

setWeight('neuron_y', 'neuron_h1', 1) 
setWeight('neuron_y', 'neuron_h2', -2) 
setWeight('neuron_y', 'neuron_h3', 1)

Setup thresholds


In [ ]:
setThreshold('neuron_x1', 0.9)
setThreshold('neuron_x2', 0.9)

setThreshold('neuron_h1', 0.9)
setThreshold('neuron_h2', 1.9)
setThreshold('neuron_h3', 0.9)

setThreshold('neuron_y', 0.9)

Simulate sensor input,then observe outputs of neurons


In [ ]:
### Wait for a while until action potential quiet down.
emptyLogs()
sleep(REFRACTORY_PERIOD) 
mergeLogs()

In [ ]:
### Simulate sensor input,force neuron_x1 to fire
emptyLogs()
sleep(REFRACTORY_PERIOD)
fire('neuron_x1') 
mergeLogs()

In [ ]:
### Simulate sensor input,force neuron_x2 to fire
emptyLogs()
sleep(REFRACTORY_PERIOD)
fire('neuron_x2') 
mergeLogs()

In [ ]:
### Simulate sensor input,force neuron_x1 and neuron_x2 to fire
emptyLogs()
sleep(REFRACTORY_PERIOD)
fire('neuron_x1')
fire('neuron_x2') 
mergeLogs()

In [ ]:
for neuron in reversed(neurons): printConfig(neuron)

Stop the demo


In [95]:
# Stopping
the_client.stop()
the_client = None
print ('\n[________________ Demo stopped ________________]\n')


[Closed: ('192.168.0.114', 1883)]

[________________ Demo stopped ________________]